#include <stdio.h>      // 包含标准输入输出库函数，如 printf、scanf
#include <stdlib.h>     // 包含 malloc、free 等动态内存分配函数
#include <string.h>     // 包含字符串操作函数，如 strcpy、strcmp
#include <windows.h>    // 包含 Windows 专用控制台函数，用于设置文字颜色

#include "attendance.h" // 包含我们自己写的头文件，其中声明了结构体和函数

// ========== 全局变量 ==========

// 定义一个全局变量 studentHead，指向学生链表的第一个节点（头指针）
// 初始时为空（NULL），表示当前还没有学生
Student *studentHead = NULL;

// 定义一个全局变量 recordHead，指向课程记录链表的第一个节点
// 用于存储每一节课的考勤信息
ClassRecord *recordHead = NULL;

// ========== 控制台颜色 ==========

// 这个函数用于设置控制台文字的颜色
// 参数 color 是颜色代码（比如 7 表示白色，10 表示绿色，12 表示红色）
// SetConsoleTextAttribute 是 Windows 的系统函数，用来改变命令行窗口颜色
void setColor(int color) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}

// ========== 学生管理功能 ==========

// 添加一个学生
void addStudent() {
    // 动态分配一个 Student 结构体的内存空间，用 malloc 函数
    Student *p = (Student*)malloc(sizeof(Student));

    // 提示用户输入学生信息
    printf("请输入 学号 姓名 班级：");
    // 使用 scanf 获取输入的数据，并保存在结构体成员中
    scanf("%s %s %s", p->id, p->name, p->className);

    // 将新添加的学生插入到链表的最前面
    // p->next 指向当前链表的第一个学生
    p->next = studentHead;
    // 然后更新 studentHead，让它指向新添加的学生
    studentHead = p;

    // 输出成功提示
    setColor(10);  // 设置字体为绿色
    printf(" 学生添加成功！\n");
    setColor(7);   // 恢复默认颜色（白色）
}

// 显示所有学生的信息
void showStudents() {
    // 定义指针 p 用于遍历链表
    Student *p = studentHead;

    setColor(11); // 蓝色字体显示表头
    printf("\n%-10s %-10s %-10s\n", "学号", "姓名", "班级");
    setColor(7);  // 恢复默认颜色

    // 循环遍历整个链表
    while (p) {
        // %-10s 表示左对齐、占10个字符宽度
        printf("%-10s %-10s %-10s\n", p->id, p->name, p->className);
        // 指针后移，访问下一个学生
        p = p->next;
    }
}

// 删除某个学生
void deleteStudent(char *id) {
    Student *p = studentHead; // 当前节点指针
    Student *pre = NULL;      // 前一个节点指针，用于链表删除操作

    // 遍历整个链表，查找学号匹配的学生
    while (p) {
        // strcmp 比较字符串是否相等
        if (strcmp(p->id, id) == 0) {
            // 找到目标学生
            if (pre) pre->next = p->next; // 如果不是第一个节点，让上一个节点跳过当前节点
            else studentHead = p->next;   // 如果是第一个节点，直接更新头指针

            free(p); // 释放内存，防止内存泄漏

            setColor(12); // 红色显示提示
            printf(" 已删除学号 %s\n", id);
            setColor(7);
            return; // 删除后直接返回
        }
        // 指针后移，继续查找
        pre = p;
        p = p->next;
    }
    // 如果循环结束仍未找到
    printf("未找到该学生！\n");
}

// ========== 考勤管理功能 ==========

// 开始考勤（输入一节课的出勤信息）
void startAttendance(int lessonNo) {
    // 创建一个课程记录节点
    ClassRecord *cr = (ClassRecord*)malloc(sizeof(ClassRecord));

    cr->lessonNo = lessonNo;  // 保存当前课次编号
    cr->attList = NULL;       // 当前课程的考勤链表初始化为空
    cr->next = recordHead;    // 将新课程插入链表头部
    recordHead = cr;          // 更新链表头指针

    // 开始遍历学生链表，对每个学生进行考勤
    Student *p = studentHead;
    printf("\n 第%d节课考勤：\n", lessonNo);

    while (p) {
        int st; // 存储当前学生的出勤状态（1 出勤，0 缺勤）
        printf("学号:%s 姓名:%s 出勤输入1 缺勤输入0: ", p->id, p->name);
        scanf("%d", &st); // 从键盘输入考勤状态

        // 创建一个新的考勤节点
        Attendance *a = (Attendance*)malloc(sizeof(Attendance));
        strcpy(a->studentId, p->id); // 将学生学号复制进考勤记录
        a->status = st;              // 记录出勤或缺勤状态
        a->next = cr->attList;       // 插入到链表头
        cr->attList = a;             // 更新链表头

        // 移动到下一个学生
        p = p->next;
    }

    setColor(10);
    printf(" 考勤记录完成！\n");
    setColor(7);
}

// 查看某节课的考勤情况
void showLessonAttendance(int lessonNo) {
    ClassRecord *cr = recordHead;

    // 查找对应的课程记录
    while (cr && cr->lessonNo != lessonNo) cr = cr->next;

    // 如果没找到
    if (!cr) {
        printf(" 未找到第%d节课记录！\n", lessonNo);
        return;
    }

    // 如果找到了，遍历其考勤记录链表
    Attendance *a = cr->attList;
    setColor(14); // 黄色字体
    printf("\n第%d节课考勤情况：\n", lessonNo);
    printf("%-10s %-10s %-10s\n", "学号", "姓名", "状态");
    setColor(7);

    while (a) {
        // 通过学号查找对应的学生姓名
        Student *p = studentHead;
        while (p && strcmp(p->id, a->studentId) != 0) p = p->next;

        // 打印考勤信息
        if (p) {
            printf("%-10s %-10s ", p->id, p->name);
            if (a->status) {
                setColor(10);  // 出勤绿色
                printf("出勤\n");
                setColor(7);
            } else {
                setColor(12);  // 缺勤红色
                printf("缺勤\n");
                setColor(7);
            }
        }
        a = a->next;
    }
}

// 查看某个学生所有课次的考勤情况
void showStudentAttendance(char *id) {
    ClassRecord *cr = recordHead;

    printf("\n学号 %s 的考勤情况：\n", id);

    // 遍历每一节课
    while (cr) {
        Attendance *a = cr->attList;
        // 遍历该节课的考勤链表
        while (a) {
            // 如果该学生在这一节课中存在考勤记录
            if (strcmp(a->studentId, id) == 0) {
                printf("第%d节课: %s\n", cr->lessonNo, a->status ? "出勤" : "缺勤");
            }
            a = a->next;
        }
        cr = cr->next;
    }
}

// ========== 统计功能部分 ==========

// 统计某一节课的出勤率
void countLessonRate(int lessonNo) {
    ClassRecord *cr = recordHead;

    // 查找对应的课程记录
    while (cr && cr->lessonNo != lessonNo) cr = cr->next;

    if (!cr) {
        printf("未找到该课次！\n");
        return;
    }

    int total = 0;   // 总人数
    int present = 0; // 出勤人数

    Attendance *a = cr->attList;
    while (a) {
        total++;                 // 每遇到一个学生，总人数加1
        if (a->status == 1) present++; // 如果出勤，出勤人数加1
        a = a->next;
    }

    // 计算百分比并输出
    printf("第%d节课出勤率: %.2f%%\n", lessonNo, (double)present / total * 100);
}

// 统计某个学生缺勤的次数
void countStudentAbsence(char *id) {
    ClassRecord *cr = recordHead;
    int cnt = 0; // 统计缺勤次数

    // 遍历所有课程
    while (cr) {
        Attendance *a = cr->attList;
        while (a) {
            // 如果学号匹配且状态为缺勤
            if (strcmp(a->studentId, id) == 0 && a->status == 0) {
                cnt++;
            }
            a = a->next;
        }
        cr = cr->next;
    }

    printf("学号 %s 缺勤次数: %d\n", id, cnt);
}
